#include <iostream>
#include <math.h>
#include <array>
#include <time.h>
#include <conio.h>
using namespace std;
// write by XSYangtuo
// welcome to play and more pull request！
// version 1.0
enum ttype {//枚举状态
    nothing,t1,t2,t3,t4,t5,t6,t7,t8,
    diso_none,//未打开的空白
    o_none,//打开但未处理的空白
    sign_none,//标记的空白
    sign_fire=100,//标记的雷
    fire = 101//未标记未打开的雷
};
int row = 26;//边长
//ttype **the;//
ttype the[42][42];//原本想用动态数组，谁知哎，我再修炼三百年
int ti = 30;//雷数
char unk = '#';
char sign = '@';
int clip[2];//鼠标


bool setting(){
    system("cls");
    cout << "输入[]内的数字进行对应的修改！" << endl;
    cout << "[0]修改游戏大小" << endl;
    cout << "[1]修改雷的数量" << endl;
    cout << "[2]修改字符标识" << endl;
    cout << "[m]返回上一层" << endl;
    switch (getch())
    {
        case 'm':return false;break;
        case '0':
            cout << "请输入修改后的边长，请不要太大，最好在30以内，最多40，否则可能串行,<enter>确认修改"<<endl;
            cin >> row;
            cin.get();
            return true;
            break;
        case '1':
            cout << "请输入修改后的数量，请不要太多，否则你会持续裂开,最多不超过总数："<< row*row << ",否则程序将停止工作<enter>确认修改"<<endl;
            cin >> ti;
            cin.get();
            return true;
            break;
        case '2':
            cout << "请输入用于替换"<<unk<<"的字符"<<endl;
            unk = getch();
            cout << "请输入用于替换"<<sign<<"的字符"<<endl;
            sign = getch();
            cout << "已修改 单击<enter>继续" <<endl;
            cin.get();
            return true;
        default:return true;break;
    }
}
void displayti(){//显示内容
    system("cls");
    cout << "扫雷,输入h查看帮助" << endl << ' ';
    for(int ia = 1;ia < row+1;ia++){
        for(int ib = 1;ib < row+1;ib++){
            if(ia == clip[0] && ib == clip[1]) cout << "\b[";
            if(the[ia][ib] == diso_none ||the[ia][ib] == fire)cout << unk;
            else if(the[ia][ib] == sign_none ||the[ia][ib] == sign_fire)cout << sign;
            else cout << the[ia][ib];
            cout << ' ';
            if(ia == clip[0] && ib == clip[1]) cout << "\b]";
        }
        cout << endl << ' ';
    }
}
bool swe(){//确定,当返回true时则触雷
    if(the[clip[0]][clip[1]] == sign_fire||the[clip[0]][clip[1]] == sign_none)return false;
    if(the[clip[0]][clip[1]] == fire)return true;
    the[clip[0]][clip[1]] = o_none;
    bool is_inof = true;//是否仍有未处理的o_none
    while(is_inof){//之所以不用递归是怕爆栈
        is_inof = false;//初始为否
        for(int ia = 1;ia < row+1;ia++){//一次遍历
            for(int ib = 1;ib < row+1;ib++){
                if(the[ia][ib] == o_none){
                    is_inof = true;
                    the[ia][ib] = (ttype)  ((the[ia-1][ib-1]+
                                            the[ia][ib-1]+
                                            the[ia+1][ib-1]+
                                            the[ia-1][ib]+
                                            the[ia+1][ib]+
                                            the[ia-1][ib+1]+
                                            the[ia][ib+1]+
                                            the[ia+1][ib+1])/100);//雷数量
                    if(the[ia][ib] == nothing){//o_none 扩散
                        the[ia-1][ib-1] = the[ia-1][ib-1] == diso_none ? o_none:the[ia-1][ib-1];
                        the[ia][ib-1] = the[ia][ib-1] == diso_none ? o_none:the[ia][ib-1];
                        the[ia+1][ib-1] = the[ia+1][ib-1] == diso_none ? o_none:the[ia+1][ib-1];
                        the[ia-1][ib] = the[ia-1][ib] == diso_none ? o_none:the[ia-1][ib];
                        the[ia+1][ib] = the[ia+1][ib] == diso_none ? o_none:the[ia+1][ib];
                        the[ia-1][ib+1] = the[ia-1][ib+1] == diso_none ? o_none:the[ia-1][ib+1];
                        the[ia][ib+1] = the[ia][ib+1] == diso_none ? o_none:the[ia][ib+1];
                        the[ia+1][ib+1] =the[ia+1][ib+1] == diso_none ? o_none:the[ia+1][ib+1];
                    }
                }
            }
        }
    }
    return false;
}
bool mainn(){//这不是main！！！返回true则再来一次，返回false则直接退出
    //the = new ttype[row+2];
    for(int ia = 1;ia < row+1;ia++){//显示
        //the[ia] = new ttype[row+2];
        //if(ia == 0 || ia == row+1){continue;}
        for(int ib = 1;ib < row+1;ib++){
            the[ia][ib] = diso_none;
        }
    }
    clip[0] = clip[1] = row/2;
    srand((unsigned)time(NULL));//随机种子
    for(int tii = ti;tii > 0;--tii){//埋雷
        int ia =rand()%row+1;
        int ib =rand()%row+1;
        if(the[ia][ib]==fire)++tii;//如果已经是雷则再次循环
        else the[ia][ib] = fire;
    }
    char sh = '?';
    while(sh != 'm'){
        displayti();
        sh = getch();
        switch(sh){
            case 'a':clip[1] = clip[1] < 2 ? clip[1]:clip[1]-1;break;
            case 'd':clip[1] = clip[1] > row-1 ? clip[1]:clip[1]+1;break;
            case 's':clip[0] = clip[0] > row-1 ? clip[0]:clip[0]+1;break;
            case 'w':clip[0] = clip[0] < 2 ? clip[0]:clip[0]-1;break;
            case 'e'://标记
                if(the[clip[0]][clip[1]] == diso_none)the[clip[0]][clip[1]] = sign_none;
                else if(the[clip[0]][clip[1]] == fire)the[clip[0]][clip[1]] = sign_fire;
                else if(the[clip[0]][clip[1]] == sign_fire)the[clip[0]][clip[1]] = fire;
                else if(the[clip[0]][clip[1]] == sign_none)the[clip[0]][clip[1]] = diso_none;
                break;
            case ' '://打开
                if(swe()){//踩雷
                    cout << "你炸裂开了awa，按n键重新开始，m键退出" << endl;
                    while(sh != 'n'||sh != 'm'){
                        sh = getch();
                        if(sh == 'n'){return true;}
                        if(sh == 'm'){return false;}
                    }
                }
                break;
            case 'n':return true;break;//重新开始
            case 't':while(setting()){}return true;break;//设置
            case 'h'://帮助
                system("cls");
                cout << "本游戏纯键盘游玩！有点费眼睛hiahiahia" << endl;
                cout << "#代表未打开的方块,[]代表光标所处的位置" << endl;
                cout << "\"awsd\"分别对应左上下右移动光标" << endl;
                cout << "空格键打开#" << endl;
                cout << "\"e\"键标记#为@，代表它是地雷，防止误触，起到提醒作用" << endl;
                cout << "n键重新再来" << endl;
                cout << "m键退出" << endl;
                cout << "点击<enter>继续..." << endl;
                cin.get();
                break;
            default:
            break;
        }
    }
    return false;
}
int main(){system("chcp 65001");while(mainn()){}return 0;}//这里暂缓一步
//日志：方案更改：利用[]来表示鼠标
//日志：方案更改：增加外围大小